package com.imooc.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
@Aspect //引入aop包就可以使用这个注解了,说明这是一个aop
public class ServiceLogAspect {

    public static final Logger log = LoggerFactory.getLogger(ServiceLogAspect.class);

    /**
     * aop通知
     * 1.前置通知:方法调用之前执行
     * 2.后置通知:方法正常调用之后执行
     * 3.环绕通知:方法调用之前和之后都分别可以执行的通知 @around
     * 4.异常通知:方法调用过程中发生异常,则通知
     * 5.最终通知:方法调用之后执行 和2有区别,可以理解为finally,如果执行发生异常,2是不会执行,而5会执行
     */
    /**
     * 切面表达式
     * execution 代表所要执行的表达式主体
     * 第一处的* 代表方法的返回类型
     * 第二处包名 代表aop监控的类所在包位置
     * 第三处 .. 代表该包及其子包下的所有方法
     * 第四处*代表类名 代表了所有的类
     * 第五处 *(..)   *代表了所有方法,括号代表参数位置,两个点代表方法中可以有任何参数
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("execution(* com.imooc.service.impl..*.*(..))")
    public Object recordTimeLog(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("=============开始执行{}.{}===========", joinPoint.getTarget().getClass(),
                joinPoint.getSignature().getName());
        //记录开始时间
        long begin = System.currentTimeMillis();
        //执行目标service
        Object result = joinPoint.proceed();
        //记录结束时间
        long end = System.currentTimeMillis();
        //计算花费时间
        long takeTime = end - begin;
        //对花费时间进行判断并以不同方式处理
        if (takeTime > 3000) {
            log.error("================执行结束,耗时:{}毫秒================", takeTime);
        } else if (takeTime > 2000) {
            log.warn("================执行结束,耗时:{}毫秒================", takeTime);
        } else {
            log.info("================执行结束,耗时:{}毫秒================", takeTime);
        }
        return result;
    }
}